Jump to content

Security Features-Secure Boot

From RidgeRun Developer Wiki


Follow us on: YouTube Twitter LinkedIn Email Share this page

Share This Page



Introduction

Secure boot is the boot-up sequence that establishes a trusted platform for the entire software stack.

There are five vital steps in the Secure Boot Enablement Process:

  1. Generate certificates and keys, using openssl.
  2. Sign images: The SecTool provides support for signing, validation and secure debugging.
  3. Generate Fuse Blower Image with the SecTool provided, to program fuses
  4. Flash signed images, fuse blower image and reboot
  5. Secure Boot Status Check: Serial logs to check secure boot status as Secure Boot: ON

This process ensures that the platform boots up with authorized software, which is signed with the customer certificate and keys.

Sectool

SecTool is the Qualcomm proprietary tool to help enable secure boot. It has two main functions:

  • Image Generation and Handling:
    • Sign an image
    • Inspect an image
    • Generate Fuse Blower image
    • Generate Debug Policy
  • Generate certificates and keys

The SecTool package is included in within the firmware source components for the Qualcomm Linux 1.8 version.

SELinux

SELinux is a tool oriented to enhance security in Linux-based systems and provide greater control over system access. Utilizes the Linux security modules (LSM) framework to include mandatory access control (MAC) in the Linux kernel. SELinux enforces access control for applications, processes, and files through security policies. When a process requests access to a resource, SELinux first checks the Access Vector Cache (AVC) for a cached decision. If no cached permission is available, the request is evaluated by the security server using the security contexts defined in the SELinux policy. Based on this evaluation, access is either granted or denied. The LSM framework includes the following controls:

  • Discretionary access control (DAC):
    • The data owner can update and/or modify the resource, retaining full control over its contents and permissions. This is the standard form of Linux access control.
    • Certain applications with root privileges can bypass this control. Some resources are unchecked, such as the socket for example.
    • Granularity on access control may be defined based on user and group identity, like file mode –rwxr-xr-x-.
  • MAC:
    • A centralized security policy controls access permissions across the system, defining what processes can do and which resources they can interact with.
    • The policy helps isolate vulnerable or malicious applications and restricts unsafe user actions, including attempts to gain elevated privileges such as root access (UID 0).
    • It offers more detailed and flexible permission management than traditional file-based controls, enabling restrictions on specific operations such as deleting, appending to, or moving files.

SELinux supports three modes:

  • Enforcing mode: SELinux actively applies the configured SEPolicy. If an operation violates the policy rules, access is denied and the event is recorded as an access vector cache (AVC) denial in system logs such as dmesg and journalctl.
  • Permissive mode: SELinux evaluates policy rules and logs any violations into dmesg and journalctl, but it does not block access. This mode is commonly used for testing and troubleshooting policy configurations.
  • Disabled mode (default): SELinux is completely turned off, meaning that security policies are neither enforced nor monitored, and no SELinux-related events are logged.

SELinux Layers

The SELinux dynamic layer contains the SELinux-specific modifications required to initialize and enable SELinux functionality on the device when using a monolithic architecture. This layer extends the upstream Yocto meta-selinux layer and provides the additional components needed for Qualcomm platforms. It includes a kernel recipe that enables the necessary SELinux-related kernel configuration options. The recipe‑security includes:

  • Policies for booting the device to the shell.
  • Policies for Qualcomm services and test applications.
  • Policies of upstream services in the form of patches.
  • A recipe to manage compilation of Qualcomm policies.

SEPolicy

SEPolicy is the directory that contains the core SELinux policy definitions and configuration files used by the system. The base SELinux policy is provided by the upstream sepolicy package, which is fetched during the build process and extended with Qualcomm-specific policies located in layers/meta-qcom-hwe/dynamic-layers/selinux/recipes-security/sepolicy/. The policy structure follows the upstream organization, with additional Qualcomm policies integrated into the corresponding directories for applications, kernel components, system services, and other platform-specific functionality.

UEFI Secure Boot

The Qualcomm Dragonwing IQ-9075 also has UEFI Secure Boot (for the Yocto's Qualcomm Linux Distribution). The UEFI Secure Boot is a feature of the Unified Extensible Firmware Interface (UEFI) specification that establishes an interface between an operating system and the platform firmware. It ensures the code executed by the device UEFI firmware engages with the security features, and it is trusted before the OS begins booting up. Also, it defines how the UEFI authenticates images such as the Linux image, the operating system loader, systemd boot, and the device tree blob image files. Lastly, it ensures that the images are loaded only when signed by valid and authorized users by the XBL. This process also ensures Qualcomm Linux security and integrity over systems running on UEFI-based firmware. The UEFI Secure Boot allows the Qualcomm Linux users to:

  • Verify the integrity and security of a UEFI-loaded image, ensuring it is loaded in an approved manner.
  • Manage the Qualcomm Linux security policy as defined by the UEFI Secure Boot authenticated variables, which includes:
    • Platform Key (PK)
    • Key exchange keys (KEK)
    • Allowed database (dB)

Enable Secure Boot

Info
The chipset value for the Dragonwing IQ-9075 is QCS9100.LE.1.0 as well as lemans for the chipset codename.


Secure Boot is enabled by blowing a set of hardware fuses in the QFPROM. The root certificate's hash is blown into the hardware fuse, which serves as the primary RoT. Secure boot is guaranteed only after blowing a QFPROM, which is an eFuse. The first step to enable Secure Boot is to enable the Qualcomm proprietary SecTool:

Enable SecTools v2

As said previously, the SecTools should be downloaded with the firmware source components for the Dragonwing IQ-9075.

1. Go to the SecTools v2 folder. The SecTools executable is located in the following path within the firmware sources (Refer to the Qualcomm Linux 1.8 Build Guide to see which firmware distributions are available):

Info
Adjust the directory path as needed.
export FIRMWARE_ROOT=$HOME/firmware-dir/
export FIRMWARE_DISTRO=<your-distro-of-choice>
$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux

This folder has the binaries and scripts required for secure boot, image signing, and other security operations.

Enable Secure Boot by blowing the QFPROM fuse

The eFuse configuration required to enable platform secure boot includes:

  • Enabling image authentication and anti-rollback protection
  • Disabling debug and JTAG access
  • Blowing disable read/write permission fuses for the QFPROM regions.

To blow the QFPROM fuse to enable secure boot, follow these steps:

1. Obtain the unique OEM ID from Qualcomm. The ID is required when using the code authorization signing services (CASS) or Qualcomm WES services. Otherwise, you can use 0 as the value for the OEM ID. Contact the Qualcomm customer engineering team if:

  • You don't have an OEM ID
  • You don't know if your organizations has been assigned the OEM ID.

2. Generate and configure signing assets such as keys and certificates.

3. Generate a signed ELF (sec.elf) for blowing fuses.

4. Sign firmware images.

5. Flash sec.elf and signed images to the device.

Images that aren't based on Linux are signed using SecTools v2 and a local signer. This process requires that signing certificates and keys be present on the local machine where signing takes place. However, these keys aren't secure and can be exposed during and after the signing process on the machine running SecTools. Keys and certificates generated with the OpenSSL tool don't have a link to any certificate authority.

Enable Secure Boot using SecTools

1. Set the environment with the following commands:

setenv SECTOOLS=/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux
export SECTOOLS=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools
export SECTOOLS_DIR=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux

2. Locate the security Profile XML:

  • Find the lemans_security_profile.xml security profile file in meta at:
$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2
  • This XML file defines the security configuration used by SecTools.
  • The minimum SecTools version required is 1.17 or later.

3. It is recommended to use a hardware security module (HSM). If a LOCAL(insecure) signer is used, see the LOCAL signing option with the --signing-help command option.

4. All the keys and certificate generation commands are run using OpenSSL 1.1.1g (21 Apr, 2020). It is a prerequisite to install OpenSSL. (See here for OpenSSL installation instructions.)

5. Ensure that you enable secure boot on a device that is not RPMB provisioned. RPMB will be automatically provisioned with production keys after secure boot fuses are blown.

Blow QFPROM fuses

Warning
This is a one-time, irreversible process that permanently sets these values.

Qualcomm fuse programmable read-only memory (QFPROM) fuses store cryptographic keys that authenticate software images during the secure boot process. The register programming by blowing fuses is a one-time process, and it can not be reversed.The following table contains the QFPROM values and details for the Dragonwing IQ-9075:

Fuse name Start address (hex) Bit number Fuse blow value Description
Read permissions
Secondary Key derivation Key Read disable 780190 31 1 After provisioning the SKDK, blow this bit to secure the secondary key from being read back.
Write permissions
Read permissions write disable 780198 5 1 Disable further QFPROM changes to this region.
FEC enables write disable 780198 7 1 Disable further QFPROM changes to this region.
OEM configuration write disable 780198 8 1 Disable further QFPROM changes to this region.
Public key hash 0 write disable 780198 24 1 Disable further QFPROM changes to this region.
OEM secure boot write disable 780198 30 1 Disable further QFPROM changes to this region.
Secondary key derivation key write disable 780198 31 1 Disable further QFPROM changes to this region.
FEC enable
OEM secure boot FEC enable 7801A0 30 1 Enable FEC for OEM secure boot region.
Secondary key derivation key FEC enable 7801A0 31 1 Enable FEC for secondary KDF key.
OEM Config
WDOG_EN 7801A8 14 1 Prevents WDOG_DISABLE GPIO from disabling WDOG.
SHARED_QSEE_SPIDEN_DISABLE 7801A8 30 1 Qualcomm TEE secure invasive debug disable bucket.
SHARED_QSEE_SPNIDEN_DISABLE 7801A8 31 1 Qualcomm TEE secure non-invasive debug disable bucket.
SHARED_MSS_DBGEN_DISABLE 7801AC 32 1 Shared MSS invasive debug disable bucket.
SHARED_MSS_NIDEN_DISABLE 7801AC 33 1 Shared MSS non-invasive debug disable bucket.
SHARED_CP_DBGEN_DISABLE 7801AC 34 1 Shared CP invasive debug disable bucket.
SHARED_CP_NIDEN_DISABLE 7801AC 35 1 Shared CP non-invasive debug disable bucket.
SHARED_NS_DBGEN_DISABLE 7801AC 36 1 Shared NS invasive debug disable bucket.
SHARED_NS_NIDEN_DISABLE 7801AC 37 1 Shared NS non-invasive debug disable bucket.
APPS_DBGEN_DISABLE 7801AC 38 1 Disable application processor invasive debug.
APPS_NIDEN_DISABLE 7801AC 39 1 Disable application processor non-invasive debug.
SHARED_MISC_DEBUG_DISABLE 7801AC 40 1 Shared miscellaneous debug disable bucket.
EKU_ENFORCEMENT_EN 7801B0 30 1 Enable EKU field enforcement in certificates.
OEM_HW_ID[0:15] 7801B4 [47:32] 0 OEM hardware ID bits 15:0.
OEM_PRODUCT_ID[0:15] 7801B4 [63:48] 0 OEM product ID bits 15:0.
ANTI_ROLLBACK_FEATURE_EN[0] 7801BC 32 1 Enable BOOT anti-rollback.
ANTI_ROLLBACK_FEATURE_EN[1] 7801BC 33 1 Enable TZAPPS anti-rollback.
ANTI_ROLLBACK_FEATURE_EN[2] 7801BC 34 1 Enable PILSUBSYS anti-rollback.
ANTI_ROLLBACK_FEATURE_EN[3] 7801BC 35 1 Enable MSA anti-rollback.
PK hash
PK hash 0[383:0] 7802A0 [383:0] - OEM-specific root certificate PK hash.
OEM secure boot
OEM_SECURE_BOOT1_PK_HASH_IN_FUSE 780D78 4 1 Use OEM_PK_HASH for root certificate hash.
OEM_SECURE_BOOT1_AUTH_EN 780D78 5 1 Enable secure boot authentication.
OEM_SECURE_BOOT2_PK_HASH_IN_FUSE 780D78 12 1 Use OEM_PK_HASH for boot config 2.
OEM_SECURE_BOOT2_AUTH_EN 780D78 13 1 Enable secure boot configuration 2.
OEM_SECURE_BOOT3_PK_HASH_IN_FUSE 780D78 20 1 Use OEM_PK_HASH for boot config 3.
OEM_SECURE_BOOT3_AUTH_EN 780D78 21 1 Enable secure boot configuration 3.
Sec key derivation key
Sec Key derivation Key[255:0] 780D88 [255:0] - 256-bit secondary key derivation value for crypto engine.

Generate Keys and Certificates for Secure Boot

Generate local (insecure) root key and certificate

The X.509 version 3 (v3 and v3_attest) extensions define certificate attributes, usage policies, and trust constraints used during certificate generation. These extensions establish the Certificate Authority (CA) properties of the certificate. Configuring these extensions, certificates can be generated with specific capabilities such as signing authority, attestation support, key usage restrictions, and validation rules required for secure boot and authentication flows.

To generate a local root key and certificate:

1. Create the OEM-KEYS directory in the SecTools path (this is a suggested path but not required, you will need to specify OEM-KEYS directory path in later commands):

cd $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/
mkdir ./OEM-KEYS
cd ./OEM-KEYS/

2. Create an opensslroot.cfg file, using the following sample content. This configuration file will be used for generating certificate requests and managing a Certificate Authority (CA).

touch opensslroot.cfg
vi opensslroot.cfg

Find the opensslroot.cfg example file here

#
#  Copyright (c) 2013 Qualcomm Technologies, Inc.
#  All Rights Reserved.
#  Confidential and Proprietary - Qualcomm Technologies, Inc.
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#

# This definition stops the following lines choking if HOME isn't
# defined.
HOME            = .
RANDFILE        = $ENV::HOME/.rnd

# Extra OBJECT IDENTIFIER info:
#oid_file       = $ENV::HOME/.oid
oid_section     = new_oids

# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions        =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)

[ new_oids ]

# We can add new OIDs in here for use by 'ca' and 'req'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6

####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

####################################################################
[ CA_default ]

dir     = ./demoCA      # Where everything is kept
certs       = $dir/certs        # Where the issued certs are kept
crl_dir     = $dir/crl      # Where the issued crl are kept
database    = $dir/index.txt    # database index file.
#unique_subject = no            # Set to 'no' to allow creation of
# several certificates with same subject.
new_certs_dir   = $dir/newcerts     # default place for new certs.

certificate = $dir/cacert.pem   # The CA certificate
serial      = $dir/serial       # The current serial number
crlnumber   = $dir/crlnumber    # the current crl number
# must be commented out to leave a V1 CRL
crl     = $dir/crl.pem      # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE    = $dir/private/.rand    # private random number file

x509_extensions = usr_cert      # The extensions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt    = ca_default        # Subject Name options
cert_opt    = ca_default        # Certificate field options

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions    = crl_ext

default_days    = 365           # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md  = sha1          # which md to use.
preserve    = no            # keep passed DN ordering

# A few different ways of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy      = policy_match

# For the CA policy
[ policy_match ]
countryName     = match
stateOrProvinceName = match
organizationName    = match
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ req ]
default_bits        = 1024
default_keyfile     = privkey.pem
distinguished_name  = req_distinguished_name
attributes      = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert

# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret

# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix   : PrintableString, BMPString.
# utf8only: only UTF8Strings.
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
# so use this option with caution!
string_mask = nombstr

req_extensions = v3_req # The extensions to add to a certificate request

[ req_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = AU
countryName_min         = 2
countryName_max         = 2

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = Some-State

localityName            = Locality Name (eg, city)

0.organizationName      = Organization Name (eg, company)
0.organizationName_default  = Internet Widgits Pty Ltd

# we can do this but it is not needed normally :-)
#1.organizationName     = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName      = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName          = Common Name (eg, YOUR name)
commonName_max          = 64

emailAddress            = Email Address
emailAddress_max        = 64

# SET-ex3           = SET extension number 3

[ req_attributes ]
challengePassword       = A challenge password
challengePassword_min       = 4
challengePassword_max       = 20

unstructuredName        = An optional company name

[ usr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.

# This is OK for an SSL server.
# nsCertType            = server

# For an object signing certificate this would be used.
# nsCertType = objsign

# For normal client use this is typical
# nsCertType = client, email

# and for everything including object signing:
# nsCertType = client, email, objsign

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# This will be displayed in Netscape's comment listbox.
nsComment           = "OpenSSL Generated Certificate"

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move

# Copy subject details
# issuerAltName=issuer:copy

#nsCaRevocationUrl      = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName

[ v3_req ]

# Extensions to add to a certificate request

subjectKeyIdentifier=hash

#authorityKeyIdentifier=keyid:always,issuer:always

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]


# Extensions for a typical CA


# PKIX recommendation.

subjectKeyIdentifier=hash

#authorityKeyIdentifier=keyid:always,issuer:always

# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true

# Key usage: this is typical for a CA certificate. However since it will
# prevent it from being used as a test self-signed certificate, it is best to be
# left out as a default.
keyUsage = cRLSign, keyCertSign

# Some might want this also
# nsCertType = sslCA, emailCA

# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy

# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF

[ crl_ext ]

# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.

# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always

[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.

# This is OK for an SSL server.
# nsCertType            = server

# For an object signing certificate this would be used.
# nsCertType = objsign

# For normal client use this is typical
# nsCertType = client, email

# and for everything including object signing:
# nsCertType = client, email, objsign

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# This will be displayed in Netscape's comment listbox.
nsComment           = "OpenSSL Generated Certificate"

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always

# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move

# Copy subject details
# issuerAltName=issuer:copy

#nsCaRevocationUrl      = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName

# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

3. Create the v3.ext and v3_attest.ext extension files (source code for the extensions can be found in the OpenSSL Documentation):

  • v3.ext:
touch v3.ext
vi v3.ext
authorityKeyIdentifier=keyid,issuer
subjectKeyIdentifier=hash
basicConstraints=CA:true,pathlen:0
keyUsage=keyCertSign
  • v3_attest.ext:
touch v3_attest.ext
vi v3_attest.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE,pathlen:0
keyUsage=digitalSignature
extendedKeyUsage=codeSigning

4. Verify the contents in the ./OEM-KEYS directory:

ls
opensslroot.cfg  v3_attest.ext  v3.ext

Generate a key pair for secure boot

You can generate the required key pair to enable secure boot on the Dragonwing IQ-9075 with either of the supported cryptography algorithms:

  • Option 1: Generate ECDSA root key and certificate.
  • Option 2: Generate RSA client application key pair and certificate.

In the following commands, several parameters should be customized depending on the specific use case, including country, city, and organization name. The following tables provide a description of each parameter used in the ECDSA and RSA procedures.

  • ECDSA Parameters:
Field Description Meaning
C Country Name Two-letter country code used in the certificate subject, for example US.
ST State or Province Name Identifies the state, province, or region associated with the certificate owner.
L Locality Name Usually the city associated with the certificate owner.
O Organization Name Identifies the company or organization that owns the certificate.
OU Organizational Unit Identifies a department, group, or intended usage of the key or certificate.
CN Common Name Human-readable certificate name, usually identifying the Root CA or Attestation CA.
  • RSA Parameters:
Field Description Meaning
C Country Name Two-letter country code used in the certificate subject, for example US.
ST State or Province Name Identifies the state, province, or region associated with the certificate owner.
L Locality Name Usually the city associated with the certificate owner.
O Organization Name Identifies the company or organization that owns the certificate.
OU Organizational Unit Identifies a department, group, or intended usage of the key or certificate.
CN Common Name Human-readable certificate name, usually identifying the Root CA or Attestation CA.
Info
It is recommended to use the ECDSA algorithm over RSA for better security.
Generate ECDSA root key and certificate

ECDSA offers superior security and performance over the RSA algorithm and, therefore, the ECDSA support is the default configuration for SecTools. To generate the root key and certificate with the ECDSA algorithm follow these steps:

Info
Modify the algorithm-specific parameters accordingly: 'Country', 'Common Name', 'Organizational Unit', 'Locality', 'Organization', and 'State'.


1. Go to the OEM-KEYS directory and generate the ECDSA root key and certificate:

cd ./OEM-KEYS
openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_rootca.key
openssl req -new -key qpsa_rootca.key -sha384 -out rootca_pem.crt -subj '/C=<COUNTRY>/CN=<ROOT_CA_COMMON_NAME>/OU=<ORGANIZATIONAL_UNIT>/L=<LOCALITY>/O=<ORGANIZATION>/ST=<STATE>' -config opensslroot.cfg -x509 -days 7300 -set_serial 1
openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER

2. Generate the intermediate Certificate Authority (CA) key pair and certificate:

openssl ecparam -genkey -name secp384r1 -outform PEM -out qpsa_attestca.key
openssl req -new -key qpsa_attestca.key -out ca.CSR -subj '/C=<COUNTRY>/ST=<STATE>/CN=<ATTESTATION_CA_COMMON_NAME>/O=<ORGANIZATION>/L=<LOCALITY>' -config opensslroot.cfg -sha384
openssl x509 -req -in ca.CSR -CA rootca_pem.crt -CAkey qpsa_rootca.key -out ca_pem.crt -set_serial 1 -days 7300 -extfile v3.ext -sha384 -CAcreateserial
openssl x509 -inform PEM -in ca_pem.crt -outform DER -out qpsa_attestca.cer
Generate RSA key pair and certificate

The RSA signature algorithm uses asymmetric keys (public/private) to verify the authenticity and integrity of a message. Follow these steps to generate RSA Key pair and certificates.

Info
Modify the algorithm-specific parameters accordingly: 'Country', 'State', 'Common Name', 'Locality', 'Organizational Unit', 'Second Organizational Unit', 'Organization', and 'Common name'.


1. To generate the root client application key pair and certificate, run the following commands. Keys size supported also include 4096 if you desire to:

openssl genrsa -out qpsa_rootca.key 2048
openssl req -new -sha256 -key qpsa_rootca.key -x509 -out rootca_pem.crt -subj '/C=<COUNTRY>/ST=<STATE>/L=<LOCALITY>/OU="<ORGANIZATIONAL_UNIT>"/OU="<SECOND_ORGANIZATIONAL_UNIT>"/O=<ORGANIZATION>/CN="<ROOT_CA_COMMON_NAME>"' -days 7300 -set_serial 1 -config opensslroot.cfg -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sigopt digest:sha256
Info
For OpenSSL versions later than 3.x, don't pass the -sigopt digest:sha256 option.
openssl x509 -in rootca_pem.crt -inform PEM -out qpsa_rootca.cer -outform DER
openssl x509 -text -inform DER -in qpsa_rootca.cer

2. Run the following commands using a key size of 2049 to generate the attestation client application key pair and certificate:

openssl genrsa -out qpsa_attestca.key 2048
openssl req -new -key qpsa_attestca.key -out attestca.csr -subj '/C=<COUNTRY>/ST=<STATE>/L=<LOCALITY>/OU="<ORGANIZATIONAL_UNIT>"/O=<ORGANIZATION>/CN="<ATTESTATION_CA_COMMON_NAME>"' -days 7300 -config opensslroot.cfg
openssl x509 -req -in attestca.csr -CA rootca_pem.crt -CAkey qpsa_rootca.key -out attestca_pem.crt -set_serial 5 -days 7300 -extfile v3.ext -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1
Info
For OpenSSL versions later than 3.x, don't pass the -sigopt digest:sha256 option.
openssl x509 -inform PEM -in attestca_pem.crt -outform DER -out qpsa_attestca.cer

Generate SHA-384 hash for RSA and ECDSA

The SHA-384 hash will serve as the RoT, ensuring the authenticity and integrity of the software images to be flashed. This cryptographic hash is vital, as it enhances security, creates digital signatures, ensures compliance, and future-proofs. To generate the SHA-384 hash RoT, run:

openssl dgst -sha384 qpsa_rootca.cer >sha384rootcert.txt

Sign and flash the images

Prerequisites

Identify the correct images for signing by checking the following files in the metabuild:

  • $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/contents.xml
    • This file contains details about the source path and the format of each image.
    • Verify the TrustZone version in the contents.xml file:
cat contents.xml | grep -i tz
  • Expected output:
      <name>tz</name>
      <role>tz</role>
      <build_id>TZ.XF.<version>-<flavor>-1</build_id>
  • For this guide, the TZ.XF.5.29.1-00146-KODIAKAAAAANAAZT-1 version is used.
  • $FIRMWARE_ROOT/$FIRMWARE_DISTRO/common/sectoolsv2/<chipset>_security_profile.xml
    • This file contains signing-related metadata, including --image-id values and a list of images that users must sign to ensure device security.

Sign the images

This guide will sign images using SecTools v2 (version 1.43), as it is the tool provided by Qualcomm sources, although other signing methods and secure image functionality are available.

1. Go to the SecTools V2 directory:

cd $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2

2. To sign a single image, run the following command, where image.mbn is used as a placeholder name; replace it according to your requirement.


Info
The values for the Dragonwing IQ-9075 are OEM-ID=0x1, PRODUCT-ID=0xabcd, and the respective flavor for the Dragonwing IQ-9075: MAKAANAA.
$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools secure-image --sign $FIRMWARE_ROOT/$FIRMWARE_DISTRO/<TrustZone-Version>/trustzone_images/build/ms/bin/MAKAANAA/tz.mbn --image-id=TZ --security-profile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/lemans_security_profile.xml --oem-id=0x1 --oem-product-id=0xabcd --anti-rollback-version=0x0 --signing-mode=LOCAL --root-certificate=./OEM-KEYS/qpsa_rootca.cer --ca-certificate=./OEM-KEYS/qpsa_attestca.cer --ca-key=./OEM-KEYS/qpsa_attestca.key --outfile ./signed_images_out/image.mbn

Signed images will be located at the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/signed_images_out/ directory.

3. Check for images with the pil_split flag in the contents.xml file discussed previously. For these images, use the --pil-split option.

4. To sign the complete metabuild, run the following command:

$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools metabuild-secure-image --image-finder $FIRMWARE_ROOT/<firmware-distro>/QCS9100.LE.1.0/common/build/app/image_finder.py --sign --oem-id=0x1 --oem-product-id=0xabcd --anti-rollback-version=0x0 --signing-mode LOCAL --root-certificate=./OEM-KEYS/qpsa_rootca.cer --ca-certificate=./OEM-KEYS/qpsa_attestca.cer --ca-key=./OEM-KEYS/qpsa_attestca.key --chipset LEMANS --outdir meta_signing_output/ --storage ufs

The complete signed metabuild will be at the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/meta_signing_output/LEMANS/ufs/qcs9075-iq-9075-evk/ directory.

Generate the signed sec.elf image

The signed sec.elf image is a secure executable and linkable format (ELF) file with a cryptographic signature. This file being signed ensures authenticity, integrity and its origin. A fuse blower binary is used to permanently disable certain functionalities or components of a device for security reasons.

Integrate sample commands using SecTools

It is important to note that:

  • You need to ensure that values such as PK hash, OEM ID, and Product ID in the command are in hexadecimal format.
  • You can replace the value of --fuse-pk-hash-0 with the SHA 384 of OEM-KEYS/qpsa_rootca.cer. To calculate the correct PK hash value, use the following command from the OEM-KEYS directory:
openssl dgst -sha384 qpsa_rootca.cer >sha384rootcert.txt
  • Replace the digest generated here from the user Root cert in the sec.elf generation command below.

Steps to generate the sec.elf file:

1. Basic secure boot (image authentication + OEM ID + MODEL ID). Run the following command:

$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools fuse-blower --security-profile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/lemans_security_profile.xml --fuse-pk-hash-0=<sha384 of OEM-KEYS/qpsa_rootca.cer> --fuse-oem-secure-boot1-pk-hash-in-fuse --fuse-oem-secure-boot1-auth-en --fuse-oem-secure-boot2-pk-hash-in-fuse --fuse-oem-secure-boot2-auth-en --fuse-oem-secure-boot3-pk-hash-in-fuse --fuse-oem-secure-boot3-auth-en --fuse-oem-hw-id=0x0001 --fuse-oem-product-id=0xabcd --generate --sign --signing-mode=LOCAL --root-certificate=./OEM-KEYS/qpsa_rootca.cer --ca-certificate=./OEM-KEYS/qpsa_attestca.cer --ca-key=./OEM-KEYS/qpsa_attestca.key --oem-id=0x1 --oem-product-id=0xabcd --outfile basic_sec.elf
Info
The --fuse-pk-hash-0= variable needs an input in hexadecimal format, e.g: 0x1234....

2. Complete secure boot (basic secure boot + debug disable + anti-rollback + write permission disable). Run the following command:

$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools fuse-blower --security-profile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/lemans_security_profile.xml --fuse-pk-hash-0=<sha384 of OEM-KEYS/qpsa_rootca.cer> --fuse-oem-secure-boot1-pk-hash-in-fuse --fuse-oem-secure-boot1-auth-en --fuse-oem-secure-boot2-pk-hash-in-fuse --fuse-oem-secure-boot2-auth-en --fuse-oem-secure-boot3-pk-hash-in-fuse --fuse-oem-secure-boot3-auth-en --fuse-oem-secure-boot-fec-enable --fuse-wdog-en --fuse-shared-qsee-spiden-disable --fuse-shared-qsee-spniden-disable --fuse-shared-mss-dbgen-disable --fuse-shared-mss-niden-disable --fuse-shared-cp-dbgen-disable --fuse-shared-cp-niden-disable --fuse-shared-ns-dbgen-disable --fuse-shared-ns-niden-disable --fuse-apps-dbgen-disable --fuse-apps-niden-disable --fuse-shared-misc-debug-disable --fuse-eku-enforcement-en --fuse-anti-rollback-feature-en=0xF --fuse-sec-key-derivation-key=0x00 --fuse-read-permissions-write-disable --fuse-oem-configuration-write-disable --fuse-secondary-key-derivation-key-read-disable --fuse-public-key-hash-0-write-disable --fuse-oem-secure-boot-write-disable --fuse-secondary-key-derivation-key-write-disable --fuse-secondary-key-derivation-key-fec-enable --fuse-fec-enables-write-disable --fuse-write-permissions-write-disable  --generate --sign --fuse-oem-hw-id=0x0001 --fuse-oem-product-id=0xabcd --signing-mode=LOCAL --root-certificate=./OEM-KEYS/qpsa_rootca.cer --ca-certificate=./OEM-KEYS/qpsa_attestca.cer --ca-key=./OEM-KEYS/qpsa_attestca.key --oem-id=0x1 --oem-product-id=0xabcd --outfile sec.elf


Info
The OEM_enable_bootup_from_a_b_partition configuration is optional and located in $FIRMWARE_ROOT/$FIRMWARE_DISTRO/<TrustZone-Version>/trustzone_images/ssg/securemsm/trustzone/qsee/mink/oem/config/lemans/oem_config.xml Its default value is 0 and when set to 1 and devcfg is recompiled, it enables rollback safety. After the boot confirmation using SMC from UEFI or client applications, it allows TrustZone to update image rollback versions.


The sec.elf images will be in the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ path.

Validate Signed Images and sec.elf with SectoolsV2

The --validate option is available to check if the image signature is compatible with a sec.elf file. To validate a complete metabuild, run the following command:

$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools metabuild-secure-image -v --image-finder $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/app/image_finder.py --chipset LEMANS --storage ufs --flavor MAKAANAA --outdir $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/meta_signing_output_custom --oem-id=0x1 --oem-product-id=0xabcd --anti-rollback-version=0x0 --signing-mode LOCAL --root-certificate=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_rootca.cer --ca-certificate=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.cer --ca-key=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.key --fuse-blower-images $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/sec.elf --sign --validate

This will add the following validation messages to the signing:

Parsed 1 Security Profile.
Parsing infile.
Performing --sign operation.
Completed --sign operation.
Performing --validate operation.
Validating infile and --fuse-blower-images against --security-profile.
Passed validation against Security Profile.
Validating infile and --fuse-blower-images against the fuse values of --fuse-blower-images.
Passed validation against the fuse values of --fuse-blower-images.
Completed --validate operation.

You can also validate a single image with the following command. The command will use the previous generated single image, adapt the command with the desired signed image to verify:

$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/ext/Linux/sectools secure-image $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/meta_signing_output/LEMANS/ufs/default/aop.mbn --image-id AOP --security-profile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/lemans_security_profile.xml --outfile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/signed_images_out/aop.mbn --oem-id=0x1 --oem-product-id=0xabcd --anti-rollback-version=0x0 --signing-mode LOCAL --root-certificate=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_rootca.cer --ca-certificate=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.cer --ca-key=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.key --fuse-blower-images $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/sec.elf --sign --validate

In this case, if the validation is successful, there will be no output. Otherwise, an error message will be displayed.

Flash the Images

Attention
The steps moving forward have not been verified by the RidgeRun team and were extracted from the Official Qualcomm Documentation. Please be aware of this when following this guide.


Refer to the previous table in the #Blow QFPROM fuses to see the list of fuses to configure.

1. Replace all binaries with the signed non Linux binaries generated in #Sign the images, including progr_firehose_ddr.elf

  • To replace PIL images, replace the existing PIL images with their corresponding signed versions generated earlier.
  • Move to the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw path:
cd $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw
  • If the directory does not exist, extract the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw.zip file:
unzip $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw.zip
cd $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw
  • Replace the PIL split binaries and the .mdt files generated in the signed output into the extracted directory $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw/lib/firmware/updates/qcom/qsc9100
  • Zip the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw directory with the QCS9100_fw.zip name.
zip -rq $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/build/ufs/bin/QCS9100_fw
  • Recompile the Yocto build.
bitbake qcom-minimal-image

3. To flash all the signed binaries to the device, follow the Flashing an Image Guide.

4. After generating the signed images and sec.elf, enable secure boot:

a. Flash sec.elf by updating the correct rawprogramX.xml file. Find the rawprogramX.xml file with the property label="secdata" and update the filename in that entry with sec.elf.
b. Flash the signed images and sec.elf using the flash procedure from the Flashing an Image Guide.
c. Flash the image using PCAT.
d. Verify Secure Boot by checking the XBL logs. These logs contain information about the boot interface, Secure Boot status, boot configuration JTAG ID, OEM ID, and serial number:
S - Format: Log Type - Time(microsec) - Message - Optional Info
S - Log Type: B - Since Boot(Power On Reset),  D - Delta,  S - Statistic
S - QC_IMAGE_VERSION_STRING=BOOT.MXF.1.0.c1-00037-KODIAKLA-1
S - IMAGE_VARIANT_STRING=SocKodiakLAA
S - OEM_IMAGE_VERSION_STRING=hu-apasunur-hyd
S - Boot Interface: USB **
S - Secure Boot: On **
S - Boot Config @ 0x00786070 = 0x000000c1
S - JTAG ID @ 0x00786130 = 0x001970e1
S - OEM ID @ 0x00786138 = 0x00000000
S - Serial Number @ 0x00786134 = 0x4172f1dd

Perform VIP Flashing

When Secure Boot is enabled, each stage of the boot chain verifies the digital signature of the next stage before allowing it to execute. Starting from the Primary Boot Loader (PBL), every boot component must be authenticated; if a signature verification fails at any point, the boot process is immediately halted. This mechanism ensures that only trusted and signed software is executed on the device, protecting it from unauthorized or malicious code

The Dragonwing IQ-9075 also supports Validated Image Programming (VIP), which provides protection during firmware flashing. Once Secure Boot is permanently enabled, the device only accepts signed images. In VIP mode, QDL validates all data sent to the target by computing hashes and comparing them against a pre-generated digest table. Packets whose digests match the expected values are accepted, while any mismatch causes the packet to be rejected and the flashing process to stop. Before performing VIP flashing, the required digest table must be generated, ensuring that only authorized images and commands can be programmed onto the device. To generate a table of digests, run QDL with the --create-digests option, providing a path to store the VIP tables. Note that --create-digests implicitly enables dry-run mode, so no device connection is required. To install and create the digests table, follow these steps:

Install QDL

Run these commands on the desired path where the qdl sources will be, this guide suggests to install the qdl tool in your home directory. For more information on the qdl tool and VIP Flashing, see the QDL GitHub repository:

1. Install dependencies:

sudo apt update
sudo apt install git build-essential libxml2-dev libusb-1.0-0-dev libzip-dev meson ninja-build help2man pkg-config

2. Clone the qdl sources repository and compile the meson build:

git clone https://github.com/linux-msm/qdl.git
meson setup build
meson compile -C build

Create Digests Table

Create a vip directory and the table of digests (Refer to the #Sign images and copy .auth key/signed files to EFI partition section for the environment variable):

cd $BINARIES_PATH
mkdir vip
qdl --create-digests=./vip prog_firehose_ddr.elf rawprogram*.xml patch*.xml

This should generate three different types of files:

  • DIGEST_TABLE.bin: contains the sha256 table of digests for all firehose packets to be sent to the target. This is an intermediary table and is used only for the subsequent generation of DigestsToSign.bin and ChainedTableOfDigests<x>.bin files, and it is not directly involve in the flashing process.
  • DigestsToSign.bin: contains the first 53 digests and the sha256 of ChainedTableOfDigests0.bin. This file must be converted to MBN format and then signed with sectools and MBN version 6:
cd vip/
$SECTOOLS_DIR/sectools mbn-tool generate --data DigestsToSign.bin --mbn-version 6 --outfile DigestsToSign.bin.mbn
$SECTOOLS_DIR/sectools secure-image --sign DigestsToSign.bin.mbn --image-id VIP --signing-mode LOCAL --outfile DigestsToSign.bin.signed.mbn --security-profile $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/lemans_security_profile.xml --root-certificate $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_rootca.cer --ca-certificate $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.cer --ca-key $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/OEM-KEYS/qpsa_attestca.key

Validate VIP tables without hardware

It is possible to test that the signed digest tables match the data that will be sent with the --dry-run and --vip-table-path options before flashing a real device:

cd ..
qdl --dry-run --vip-table-path=./vip prog_firehose_ddr.elf rawprogram*.xml patch*.xml

If the run is successful, the command will display the following output:

65 patches applied
partition 1 is now bootable

QDL can perform a complete simulated Firehose flashing session by calculating the SHA-256 hash of every packet that would be transmitted and validating it against the corresponding entries in the loaded digest tables. Any detected mismatch is reported and displayed before the process exits, allowing all issues to be reviewed at once. This validation step helps identify inconsistencies between the firmware data and digest tables before performing an actual flash.

Perform VIP Flashing

Warning
The steps moving forward have not been verified by the RidgeRun team and were extracted from the Official QDL Documentation. Please be aware of this when following this guide.

To flash a board using VIP mode, provide the path where the previously generated and signed tables are stored using the --vip-table-path option:

qdl --vip-table-path=./vip prog_firehose_ddr.elf rawprogram*.xml patch*.xml

Enable SELinux

The layer meta-selinux should be included in the Yocto build following the Qualcomm Linux 1.8 Build and Installation Guide. To enable SELinux for Qualcomm Linux, set the variable DEFAULT_ENFORCING to enforcing in the meta-qcom-distro/conf/distro/include/qcom-base.inc file. You can find more information of this layer in meta-selinux.

With SELinux enabled, all system objects, including, files, processes, sockets, drivers, and more, are labeled with a security context. A security context consists of a user, role, type identifier, and optional sensitivity, separated by colons. For example, user:role:type:sensitivity. SELinux includes the following features:

  • A set of valid users, roles, and types is defined in the policy.
  • Different objects are labeled with the same security context.
  • The MAC mechanism of SELinux security policies is implemented using:
    • Type enforcement (TE)
    • Role-based access control (RBAC)
    • Multilevel security (MLS)
  • Types enable the policy to specify the allowed operations.

Verify SELinux status

If SELinux is enabled, you may not be allowed to update the anti-rollback protection flag.

1. Check the current SELinux configuration of the device (either Enforcing or Permissive mode):

getenforce

This command will output either enforcing, permissive, or disabled

2. You can switch between modes running:

  • Enforcing mode:
setenforce 1
  • Permissive mode:
setenforce 0

This change won't persist after a reboot.

To either enable or disable SELinux, modify the /meta-qcom-distro/conf/distro/include/qcom-base.inc file in your build, removing or adding the following lines:

#Selinux support
DISTRO_FEATURES_FILTER_NATIVE:append = " selinux"
DISTRO_FEATURES_FILTER_NATIVESDK:append = " selinux"
DISTRO_EXTRA_RDEPENDS:append = " ${@bb.utils.contains('DISTRO_FEATURES','selinux','packagegroup-selinux-minimal','', d)}"
PREFERRED_PROVIDER_virtual/refpolicy = "refpolicy-mls"
DEFAULT_ENFORCING = "permissive"
SELINUX_FILE_CONTEXTS_EXT4 = " -f ${IMAGE_ROOTFS}/etc/selinux/mls/contexts/files/file_contexts"
EXTRA_IMAGECMD:ext4 += " ${@bb.utils.contains('DISTRO_FEATURES','selinux','${SELINUX_FILE_CONTEXTS_EXT4}','', d)}"

Modify the DEFAULT_ENFORCING flag as desired, with one of the three supported values.

To change the SELinux mode even after a reboot, edit the SELinux= variable with one of the three supported values, in the etc/selinux/config file in the Dragonwing IQ-9075. To apply the change, reboot the board.

Enable UEFI Secure Boot

Prerequisites

1. Install OpenSSL 0.9.80 or later on the Linux Host computer:

sudo apt update
sudo apt install openssl

2. Install the following efitools:

  • cert-to-efi-sig-list: converts OpenSSL certificates to EFI signature lists.
  • sign-efi-sig-list: signs the EFI signature list.
  • hash-efi-sig-list: creates a hash signature list entry from a binary.
sudo apt install efitools

Verify the installation running:

which cert-to-efi-sig-list
which sign-efi-sig-list
which hash-to-efi-sig-list

3. Install UUIDGEN:

sudo apt install uuid-runtime


Replay protected memory block (RPMB) provisioning must be enabled for UEFI secure boot enablement. This is a secure physical partition in storage devices such as UFS/eMMC flash. It stores critical data and protects it from tampering and rollback. This partition is only accessible from Qualcomm TEE. RPMB key provisioning is required to read and write from this partition, which is a one-time, irreversible process that can not be overwritten or erased when completed. Every access to the memory block is authenticated, which allows data storage to be replay-protected and require authentication.

{message|type=warning|text=If UEFI Secre Boot is enabled without HW secure boot, Secure Boot activation may be unavailable in the future. }}

Configure UEFI Secure Boot

Generate key and certificate pairs

For signing and authentication, the following algorithms are supported for key generation:

  • RSA 2048/4096 with SHA-256/SHA384 hash algorithm
  • ECDSA secp256r1/secp384r1

The following guide will use the RSA 2048 and SHA-256, but you can adjust the commands to your liking. For ECC, replace rsa:2048 with ec:secp384r1, and for SHA384, replace -sha256 with -sha384 in the next steps:

1. Create a directory where the keys will be stored

cd $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2
mkdir uefi-keys
export UEFI_KEYS_PATH=$FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/uefi-keys
cd uefi-keys/

2. Generate GUID and three new keys with self-signed certificates in CRT/PEM format and keys in .key format:

uuidgen --random > GUID.txt

3. Create a PK key pair and certificate (replace the common name variable as desired):

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom PK/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256
3.1. Convert the .crt file into the .cer file:
openssl x509 -outform der -in PK.crt -out PK.cer
3.2. Convert the .crt file into the .esl file:
cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
3.3. Sign and generate the .auth file with the previous generated files:
sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth

4. Create a KEK key pair and certificate (replace the common name variable as desired):

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom KEK/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256
4.1. Convert the .crt file into the .cer file:
openssl x509 -outform der -in KEK.crt -out KEK.cer
4.2. Convert the .crt file into the .esl file:
cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
4.3. Sign and generate the .auth file with the previous generated files:
sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth

5. Create a dB key pair and certificate (replace the common name variable as desired):

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom DB/" -keyout db.key -out db.crt -days 3650 -nodes -sha256
5.1. Convert the .crt file into the .cer file:
openssl x509 -outform der -in db.crt -out db.cer
5.2. Convert the .crt file into the .esl file:
cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
5.3. Sign and generate the .auth file with the previous generated files:
sign-efi-sig-list -k KEK.key -c KEK.crt db db.esl db.auth

Sign images and copy .auth key/signed files to EFI partition

The EFI partition has three main components: EFI, loader, and ostree with information relevant to EFI while systemd-boot is being used. This EFI system partition contains required files to boot the system and managing updates, while the DTB partition has hardware descriptions and configuration information. The systemd-boot validates signed images and enrolls the following:

  • Systemd-boot uses the UEFI secure boot keys, which are placed in a key-specific directory for key enrollment, and stores them in the RPMB during UEFI boot time services.
  • Systemd-boot wait time can be configured , as Kernel loading is delayed during this wait time, allowing review and selecting options in the systemd-boot menu.
  • Device tree files are located in the dtbmountedbin/dtb path, which are used by UEFI during runtime to configure the platform hardware. Since DTB files are not PE-format images, the signing process generates separate .sig files, which are stored alongside the corresponding DTB files.

Follow the next steps to place the signed images and keys in an EFI partition:

1. Locate the efi.bin and dtb.bin file paths in the $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/contents.xml file to obtain the efi.bin and dtb.bin files from the build:

Info
Adjust the directory path as needed.
cat $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/contents.xml
export BINARIES_PATH=<your-uefi-binaries-path>
cd $BINARIES_PATH

2. Create the directories that will serve as a mount point for the efi.bin and dtb.bin files:

mkdir efimountedbin dtbmountedbin

3. Mount the efi.bin file:

sudo mount efi.bin efimountedbin

4. Mount the dtb.bin file:

sudo mount dtb.bin dtbmountedbin

5. Create an authkeys directory to enroll keys in the efimountedbin directory:

sudo mkdir -p efimountedbin/loader/keys/authkeys

6. Copy the .auth files to the authkeys directory:

sudo cp $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/uefi-keys/*.auth efimountedbin/loader/keys/authkeys/

7. Create an authkeys directory to enroll keys in the dtbmountedbin directory:

sudo mkdir -p dtbmountedbin/loader/keys/authkeys

8. Copy the .auth files to the authkeys directory:

sudo cp $FIRMWARE_ROOT/$FIRMWARE_DISTRO/QCS9100.LE.1.0/common/sectoolsv2/uefi-keys/*.auth dtbmountedbin/loader/keys/authkeys/

Sign efi images

EFI boot images are signed with the sbsign tool, such as the bootaa64.efi image. This tool is required to enable UEFI Secure boot and can only sign PE images with the .efi extension.

1. Create a temporary directory in the $BINARIES_PATH directory:

mkdir images

2. Copy the boota64.efi file from the /efimountedbin/EFI/BOOT directory and the vmlinuz.<version> from the efimountedbin/ostree/poky-<hash> directory (adjust the commands with your corresponding version and hash):

cp efimountedbin/EFI/BOOT/bootaa64.efi efimountedbin/ostree/poky-<hash>/vmlinuz.<version> images/

3. Sign the images:

cd images/
sudo sbsign --key $UEFI_KEYS_PATH/db.key --cert $UEFI_KEYS_PATH/db.crt bootaa64.efi --output $BINARIES_PATH/bootaa64.efi
sudo sbsign --key $UEFI_KEYS_PATH/db.key --cert $UEFI_KEYS_PATH/db.crt vmlinuz.<version> --output $BINARIES_PATH/vmlinuz.<version>

Sign dtb images

UEFI secure boot expects signed images in the PE format, as authenticated images are regular APIs and typically are in this format. The signature header and size are appended to the PE format header that the file already has, and signatures are appended to the end of the signed file. The absence of this PE format header may lead into issues as the UEFI secure boot verification will fail, thus making impossible the usage of standard tools for image verification. For dtb files, which are the only images that UEFI secure boot verifies without PE format header, the OpenSSL cms command may be use as an alternative to generate signature files for non-PE files.

To sign the non-PE dtb:

1. Copy the combined-dtb.dtb file to the images directory:

cd $BINARIES_PATH
cp dtbmountedbin/combined-dtb.dtb images/
cd images/

2. Sign the image with the following command:

sudo openssl cms -sign -inkey $UEFI_KEYS_PATH/db.key -signer $UEFI_KEYS_PATH/db.crt -binary -in combined-dtb.dtb --out combined-dtb.sig -outform DER

Finish configuration

Now that both the EFI and dtb files are signed, finish configuration and flash the binaries:

1. Copy the signed combined-dtb.sig, vmlinuz.<version>, and boota64.efi files to their respective mounted points:

sudo cp combined-dtb.sig ../dtbmountedbin/
sudo cp vmlinuz-<version> ../efimountedbin/ostree/poky-<hash>
sudo cp bootaa64.efi ../efimountedbin/EFI/BOOT/

2. Configure timeout duration of systemd-boot manager to display menu:

2.1. Go to the loader.conf path:
cd $BINARIES_PATH/efimountedbin/loader
2.2. Edit the loader.conf file, add the line timeout 10 to set the boot menu timeout and save the file:
sudo vi loader.conf

timeout 10

3. Unmount the EFI binary to retrieve the latest efi.bin file:

 cd $BINARIES_PATH
sudo umount efimountedbin

4. Unmount the DTB binary to retrieve the latest dtb.bin file:

sudo umount dtbmountedbin


Warning
The steps moving forward have not been verified by the RidgeRun team and were extracted from the Official Qualcomm Documentation. Please be aware of this when following this guide.


5. To flash signed images and keys on the target, bring the device into the Fastboot mode and use the following commands to update the efi.bin and dtb.bin images:

fastboot flash efi <efi binary location>
fastboot flash dtb_a <dtb binary location>

Enable UEFI secure boot from systemd-boot menu

Warning
The steps moving forward have not been verified by the RidgeRun team and were extracted from the Official Qualcomm Documentation. Please be aware of this when following this guide.


Ensure that the EFI signed images and the secure boot keys are first generated and flashed onto the target, as well as the timeout 10 configuration. Remember that key enrollment using systemd-boot manager to store keys into RPMB is a one-time operation, and after a successful key enrollment, the reprovisioning and updating of UEFI secure boot keys isn't possible.


Follow the next steps to enable the UEFI secure boot on the device:

1. In the next bootup after UEFI secure boot is loaded, the systemd-boot manager will display the following interactive menu:

Qualcomm Linux 1.5-ver.1.1 (ostree:0) Enroll Secure Boot keys: authkeys
Boot in 10 s. ?????????????????????????????????????????????????
Boot in 9 s. ?????????????????????????????????????????????????
Boot in 8 s.

2. Use vol- key to stop the timeout, which displays Enroll Secure Boot keys: authkeys.

3. Use power key to start enrollment. This is followed by a timeout with option to abort this enrollment operation. In this timeout duration, don't use any key. After the timeout is done, key enrollment will be executed. A successful key enrollment procedure will display:

Qualcomm Linux 1.5-ver.1.1 (ostree:0) Enroll Secure Boot keys: authkeys Enrolling secure boot keys from directory: \loader\keys\authkeys
Warning: Enrolling custom Secure Boot keys might soft-brick your machine!
Enrolling in 15 s, press any key to abort.
...
Enrolling in  0 s, press any key to abort.
Custom Secure Boot keys successfully enrolled, rebooting the system now!

4. After key enrollment, UEFI automatically switches from SetupMode to UserMode, then the systemd-boot triggers a reboot.

5. On next device bootup, UEFI starts in UserMode and the UEFI secure boot is enabled. A successful enablement of UEFI secure boot will display:

EFI stub: Booting Linux Kernel...
EFI stub: Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path
EFI stub: UEFI Secure Boot is enabled.
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...

6. Once the UEFI secure boot is successfully enabled, revert the systemd-boot manager timeout configuration.

Hash unsigned images and update DB for image authentication

Authentication through the hash of images stored in the signature database (dB) is allowed for UEFI secure boot. This does not require the images to be signed or the certificates to be present in the dB. This process is reserved for content that can't be signed or altered from its vendor-provided state. if the image hash is available in the database deny (dBX) list, the trust of signed binaries can be removed without having to revoke the corresponding keys or certificates. A use case for this may be dealing with a boot loader that was earlier signed and its vulnerable to recent exploits. It is not necessary to sign an image and create a dB hash for the same file. The following steps apply if there is no need to apply any changes, no new keys and certificates are added, and no UEFI secure boot authentication is needed for the existing images. Follow this steps to generate the hash of images and an allowed signatured dB file with the efi.bin as an example:

1. Mount the efi.bin file to the desired folder in your directory:

cd $BINARIES_PATH
mkdir efimountedbin
sudo mount efi.bin efimountedbin

2. Create a testkeys folder in the $BINARIES_PATH directory and copy pre-existing keys:

mkdir testkeys
cp $UEFI_KEYS_PATH/* testkeys/
cd testkeys/

3. Sign the images:

hash-to-efi-sig-list $BINARIES_PATH/efimountedbin/EFI/BOOT/bootaa64.efi mergedhash.esl
sign-efi-sig-list -k db.key -c db.crt db mergedhash.esl db.auth

4. Create the qckeys directory and copy the db.auth file into it:

cd $BINARIES_PATH
sudo mkdir -p efimountedbin/loader/keys/qckeys
sudo cp testkeys/db.auth efimountedbin/loader/keys/qckeys/

5. Follow the previous steps in the #Sign dtb images section onwards to sign the dtb file and generate a new efi.bin file.

6. Erase any existing UEFI secure boot keys and flash the EFI binary with fastboot.

7. Provision keys with systemd-boot, following the steps in the #Enable UEFI secure boot from systemd-boot menu section.

All unsigned files are signed with other keys and authenticated with UEFI using this method.

Cookies help us deliver our services. By using our services, you agree to our use of cookies.